﻿using System;

namespace FirstFloor.Documents.IO
{
    /// <summary>
    /// Provides a reference implementation of a package reader that is able to read encrypted package parts.
    /// </summary>
    /// <remarks>
    /// An encrypted package reader is useful when package parts are protected with a security technology such as DRM. This reader
    /// wraps an existing package reader and adds decrypting functionality. The actual decryption is implemented by the IPackageDecrypter.
    /// </remarks>
    public class EncryptedPackageReader
        : IPackageReader
    {
        private IPackageReader originalReader;
        private IPackageDecrypter decrypter;

        /// <summary>
        /// Initializes a new instance of the <see cref="EncryptedPackageReader"/> class.
        /// </summary>
        /// <param name="originalReader">The original reader.</param>
        /// <param name="decrypter">The decrypter.</param>
        public EncryptedPackageReader(IPackageReader originalReader, IPackageDecrypter decrypter)
        {
            if (originalReader == null) {
                throw new ArgumentNullException("originalReader");
            }
            if (decrypter == null) {
                throw new ArgumentNullException("decrypter");
            }
            this.originalReader = originalReader;
            this.decrypter = decrypter;
        }

        /// <summary>
        /// Initializes a new package part request.
        /// </summary>
        /// <param name="partUri">The part URI.</param>
        /// <returns>The part request.</returns>
        public IPackagePartRequest CreatePartRequest(Uri partUri)
        {
            // map uri if needed
            partUri = this.decrypter.MapPartUri(partUri);

            return new EncryptedPackagePartRequest(this.originalReader, partUri, this.decrypter);
        }

        /// <summary>
        /// Resolves the specified part uri to a public accessible uri.
        /// </summary>
        /// <param name="partUri">The part URI.</param>
        /// <returns>The resolved URI.</returns>
        /// <remarks>If the package reader does not support public accessible uris, null is returned.</remarks>
        public Uri ResolvePartUri(Uri partUri)
        {
            // all package parts must be loaded using this reader, therefore return null
            return null;
        }

        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            this.originalReader.Dispose();
        }
    }
}
